/**
 * This file is part of the CAKIS project.
 * 
 * Copyright (c) 2009-2010 - Florian Arndt, Christian Kerl
 * 
 * @license GNU Lesser General Public License v3 <http://www.opensource.org/licenses/lgpl-3.0.html>
 * @since   14.05.2010
 * @version SVN: $Id: RecipeServiceLocalImpl.java 143 2010-05-15 12:01:28Z christian-kerl@web.de $
 */
package org.cakis.server.service.impl;

import java.net.URL;
import java.util.UUID;

import javax.ejb.Stateless;

import org.cakis.server.Names;
import org.cakis.server.model.BaseProduct;
import org.cakis.server.model.ProductType;
import org.cakis.server.model.Recipe;
import org.cakis.server.model.RecipeIngredient;
import org.cakis.server.model.StockUnit;
import org.cakis.server.model.repository.ProductTypeRepository;
import org.cakis.server.model.repository.StockUnitRepository;
import org.cakis.server.service.ProductNotFoundException;
import org.cakis.server.service.RecipeImportServiceRegistry;
import org.cakis.server.service.RecipeNotFoundException;
import org.cakis.server.service.RecipeService;
import org.cakis.server.service.StockUnitNotFoundException;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.*;

/**
 * RecipeServiceLocalImpl
 *
 * @author Christian Kerl
 */
@Name(Names.RecipeServiceLocal)
@Scope(ScopeType.APPLICATION)
@Stateless
@Startup
public class RecipeServiceLocalImpl implements RecipeService.Local {
    private RecipeImportServiceRegistry registry;
    private StockUnitRepository stockUnitRepository;
    private ProductTypeRepository productTypeRepository;

    private StockUnitCleaner stockUnitCleaner;

    @In(value = Names.RecipeImportServiceRegistry, required = true, create = true)
    public void setRecipeImportServiceRegistry(RecipeImportServiceRegistry registry) {
        this.registry = registry;
    }

    @In(value = Names.StockUnitRepository, required = true, create = true)
    public void setStockUnitRepository(StockUnitRepository stockUnitRepository) {
        this.stockUnitRepository = stockUnitRepository;
        this.stockUnitCleaner = new StockUnitCleaner(stockUnitRepository);
    }

    @In(value = Names.ProductTypeRepository, required = true, create = true)
    public void setProductTypeRepository(ProductTypeRepository productTypeRepository) {
        this.productTypeRepository = productTypeRepository;
    }

    @Override
    public Recipe importRecipe(URL url, boolean addMissingStockUnitAndProductType) throws RecipeNotFoundException, ProductNotFoundException, StockUnitNotFoundException {
        Recipe cleanResult;
        Recipe result = registry.getRecipeInformation(url);

        if(result == null) {
            throw new RecipeNotFoundException(url.toString());
        }

        cleanResult = new Recipe();
        cleanResult.setUuid(UUID.randomUUID());
        cleanResult.setName(result.getName());
        cleanResult.setNumberOfPersons(result.getNumberOfPersons());
        cleanResult.setPreparationDescription(result.getPreparationDescription());

        for(RecipeIngredient ingredient : result.getIngredients()) {
            BaseProduct product = getProduct(ingredient.getProduct().getName(), addMissingStockUnitAndProductType);
            StockUnit   unit    = getUnit(ingredient.getQuantity().getUnit(), addMissingStockUnitAndProductType);

            RecipeIngredient cleanIngredient = new RecipeIngredient();
            cleanIngredient.setRecipe(cleanResult);
            cleanIngredient.setProduct(product);
            cleanIngredient.setHint(cleanIngredient.getHint());

            cleanIngredient.getQuantity().setUnit(unit);

            if(unit != null) {
                cleanIngredient.getQuantity().setQuantity(ingredient.getQuantity().getNumberOfPieces());
                cleanIngredient.getQuantity().setNumberOfPieces(0.0f);
            } else {
                cleanIngredient.getQuantity().setNumberOfPieces(ingredient.getQuantity().getNumberOfPieces());
                cleanIngredient.getQuantity().setQuantity(0.0f);
            }

            cleanResult.getIngredients().add(cleanIngredient);
        }

        return cleanResult;
    }

    private BaseProduct getProduct(String name, boolean create) throws ProductNotFoundException {
        BaseProduct result = null;

        result = productTypeRepository.findBaseProductByName(name);

        if(result == null) {
            if(create) {
                result = new ProductType();
                result.setName(name);
                result = productTypeRepository.store((ProductType) result);
            } else {
                throw new ProductNotFoundException(name);
            }
        }

        return result;
    }

    private StockUnit getUnit(StockUnit unit, boolean create) throws StockUnitNotFoundException {
        StockUnit result = null;

        try {
            if(unit.getName() != null && !unit.getName().isEmpty()) {
                result = stockUnitCleaner.getCleanStockUnit(unit);
            }
        } catch (StockUnitNotFoundException e) {
            if(create) {
                result = new StockUnit();
                result.setName(unit.getName());
                result.setSymbol(unit.getName());
                result = stockUnitRepository.store(result);
            } else {
                throw e;
            }
        }

        return result;
    }
}
